﻿using System.Collections.Generic;
using Firefly.Framework.Collections;
using Firefly.Framework.ContentManagement;
using Firefly.Framework.Graphics;
using Firefly.Framework.Input;
using Firefly.Framework.Windows;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;

namespace Firefly.Framework
{
    public abstract class Engine : Game, IInputProcessor
    {
        protected new ComponentCollection Components { get; set; }
        protected int ScreenWidth { get; set; }
        protected int ScreenHeight { get; set; }

        public Engine()
        {
            GraphicsService.Instance.Initialize(this);
            ContentService.Instance.Initialize(this);
            Content = ContentService.Instance.ContentManager;
            Content.RootDirectory = "Content";
            Components = new ComponentCollection();
        }

        protected override void Initialize()
        {
            GraphicsService.Instance.GraphicsDeviceManager.PreferMultiSampling = true;
            GraphicsService.Instance.GraphicsDeviceManager.SynchronizeWithVerticalRetrace = false;
            GraphicsService.Instance.GraphicsDeviceManager.PreferredBackBufferWidth = ScreenWidth;
            GraphicsService.Instance.GraphicsDeviceManager.PreferredBackBufferHeight = ScreenHeight;
            GraphicsService.Instance.GraphicsDeviceManager.ApplyChanges();
            IsFixedTimeStep = false;
            InitializeInputMaps();
            base.Initialize();
        }

        protected override void Update(GameTime gameTime)
        {
            InputService.Instance.Update(gameTime);
            Components.Update(gameTime);

            if (!WindowsService.Instance.Disposed)
            {
                WindowsService.Instance.Update(gameTime);
            }
        }

        protected override void Draw(GameTime gameTime)
        {
            Components.Draw(gameTime);

            if (!WindowsService.Instance.Disposed)
            {
                WindowsService.Instance.Draw(gameTime);
            }
        }

        protected override void LoadContent()
        {
            GraphicsService.Instance.LoadContent();

            try
            {
                WindowsService.Instance.LoadContent();
                WindowsService.Instance.Enabled = false;
                WindowsService.Instance.Visible = false;
            }
            catch(ContentLoadException)
            {
                WindowsService.Instance.Dispose();
            }
        }

        protected override void UnloadContent()
        {
            GraphicsService.Instance.UnloadContent();
            WindowsService.Instance.Dispose();
        }

        #region IInputProcessor Members

        public int HoldThreshold { get; set; }
        public List<KeyMap> KeyMaps { get; protected set; }
        public List<MouseButtonMap> MouseButtonMaps { get; protected set; }
        public MouseAxisMap MouseAxisMap { get; protected set; }
        public MouseScrollWheelMap MouseScrollWheelMap { get; protected set; }
        public List<GamePadButtonMap> GamePadButtonMaps { get; protected set; }
        public List<GamePadDPadMap> GamePadDPadMaps { get; protected set; }
        public List<GamePadTriggerMap> GamePadTriggerMaps { get; protected set; }
        public List<GamePadThumbStickMap> GamePadThumbStickMaps { get; protected set; }

        public abstract void InitializeInputMaps();

        #endregion
    }
}
